package com.tjakus.quartz;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import com.tjakus.logging.Logging;
import com.tjakus.properties.Property;

public class QuartzUtil {

	/**
	 * This is a static class which represents quartz jobs utilities.
	 * 
	 * @author tjakus
	 * 
	 */

	private static JobDetail jobDetailReadProperty;
	private static JobDetail jobDetailGetPage;
	private static JobDetail jobDetailSendMail;
	private static JobDetail jobDetailDBCleanup;
	private static JobDetail jobDetailUpdateStatistics;
	private static CronTrigger triggerForJobReadProperty;
	private static CronTrigger triggerForGetPageJob;
	private static CronTrigger triggerForJobSendMail;
	private static CronTrigger triggerForJobDBCleanup;
	private static CronTrigger triggerForJobUpdateStatistics;
	private static Scheduler scheduler;

	public static boolean initializeQuartzJobs() {
		/**
		 * This method initialize quartz jobs triggers. It returns true or false.
		 * 
		 */
		try {
			jobDetailReadProperty = JobBuilder.newJob(JobReadProperty.class)
					.withIdentity("JobReadProperty", "Group1").build();

			jobDetailGetPage = JobBuilder.newJob(GetPageJob.class)
					.withIdentity("GetPageJob", "Group1").build();

			jobDetailSendMail = JobBuilder.newJob(JobSendMail.class)
					.withIdentity("JobSendMail", "Group1").build();

			jobDetailDBCleanup = JobBuilder.newJob(JobDBCleanup.class)
					.withIdentity("JobDBCleanup", "Group1").build();

			jobDetailUpdateStatistics = JobBuilder.newJob(JobUpdateStatistics.class)
					.withIdentity("JobUpdateStatistics", "Group1").build();

			// Trigger ReadPropertyJob
			triggerForJobReadProperty = TriggerBuilder
					.newTrigger()
					.withIdentity("JobReadProperty", "Group1")
					.withSchedule(
							CronScheduleBuilder.cronSchedule(Property.CRON_JOB_READ_PROPERTY))
					.build();

			// Trigger GetPageJob
			triggerForGetPageJob = TriggerBuilder
					.newTrigger()
					.withIdentity("GetPageJob", "Group1")
					.withSchedule(
							CronScheduleBuilder.cronSchedule(Property.CRON_GET_PAGE_JOB))
					.build();

			// Trigger JobSendMail
			triggerForJobSendMail = TriggerBuilder
					.newTrigger()
					.withIdentity("JobSendMail", "Group1")
					.withSchedule(
							CronScheduleBuilder.cronSchedule(Property.CRON_JOB_SEND_MAIL))
					.build();

			// Trigger JobDBCleanup
			triggerForJobDBCleanup = TriggerBuilder
					.newTrigger()
					.withIdentity("JobDBCleanup", "Group1")
					.withSchedule(
							CronScheduleBuilder.cronSchedule(Property.CRON_JOB_DB_CLEANUP))
					.build();

			// Trigger JobUpdateStatistics
			triggerForJobUpdateStatistics = TriggerBuilder
					.newTrigger()
					.withIdentity("JobUpdateStatistics", "Group1")
					.withSchedule(
							CronScheduleBuilder
									.cronSchedule(Property.CRON_JOB_UPDATE_STATISTICS)).build();

			Logging.getLogger().info(
					"QuartzUtil - initializeQuartzJobs - [ SUCCESSFUL ] ");
			return true;
		} catch (Exception e) {
			Logging.getLogger().error(
					"QuartzUtil - initializeQuartzJobs - [ FAILED ] ", e);
			return false;
		}
	}

	public static boolean scheduleJobs() {
		/**
		 * This method schedules quartz jobs based on triggers. It returns true or
		 * false.
		 * 
		 */
		try {
			// Schedule jobs based on triggers
			scheduler = new StdSchedulerFactory().getScheduler();
			scheduler.start();
			scheduler.scheduleJob(jobDetailReadProperty, triggerForJobReadProperty);
			scheduler.scheduleJob(jobDetailGetPage, triggerForGetPageJob);
			scheduler.scheduleJob(jobDetailSendMail, triggerForJobSendMail);
			scheduler.scheduleJob(jobDetailDBCleanup, triggerForJobDBCleanup);
			scheduler.scheduleJob(jobDetailUpdateStatistics,
					triggerForJobUpdateStatistics);
			Logging.getLogger().info("QuartzUtil - scheduleJobs - [ SUCCESSFUL ] ");
			return true;
		} catch (SchedulerException e) {
			Logging.getLogger().error("QuartzUtil - scheduleJobs - [ FAILED ] ", e);
			return false;
		}
	}

	public static boolean rescheduleJobs() {
		/**
		 * This method reschedules quartz jobs if schedule in database has been
		 * changed. It returns true or false.
		 * 
		 */
		try {
			// Check if trigger schedule for job read property has been changed
			CronTrigger oldtrigger = (CronTrigger) scheduler
					.getTrigger(triggerForJobReadProperty.getKey());
			// If trigger schedule has been changed, reschedule job
			if (!(oldtrigger.getCronExpression().equals(triggerForJobReadProperty
					.getCronExpression()))) {
				Logging.getLogger().info(
						"QuartzUtil - rescheduleJobs - JobReadProperty - [ " + triggerForJobReadProperty.getCronExpression() +" ] ");
				scheduler.rescheduleJob(triggerForJobReadProperty.getKey(),
						triggerForJobReadProperty);
			}
			
			// Check if trigger schedule for get page job has been changed
			oldtrigger = (CronTrigger) scheduler
					.getTrigger(triggerForGetPageJob.getKey());
			// If trigger schedule has been changed, reschedule job
			if (!(oldtrigger.getCronExpression().equals(triggerForGetPageJob
					.getCronExpression()))) {
				Logging.getLogger().info(
						"QuartzUtil - rescheduleJobs - GetPageJob - [ " + triggerForGetPageJob.getCronExpression() +" ] ");
				scheduler.rescheduleJob(triggerForGetPageJob.getKey(),
						triggerForGetPageJob);
			}
			
			// Check if trigger schedule for job send mail has been changed
			oldtrigger = (CronTrigger) scheduler
					.getTrigger(triggerForJobSendMail.getKey());
			// If trigger schedule has been changed, reschedule job
			if (!(oldtrigger.getCronExpression().equals(triggerForJobSendMail
					.getCronExpression()))) {
				Logging.getLogger().info(
						"QuartzUtil - rescheduleJobs - JobSendMail - [ " + triggerForJobSendMail.getCronExpression() +" ] ");
				scheduler.rescheduleJob(triggerForJobSendMail.getKey(),
						triggerForJobSendMail);
			}
			
			// Check if trigger schedule for job DB cleanup has been changed
			oldtrigger = (CronTrigger) scheduler
					.getTrigger(triggerForJobDBCleanup.getKey());
			// If trigger schedule has been changed, reschedule job
			if (!(oldtrigger.getCronExpression().equals(triggerForJobDBCleanup
					.getCronExpression()))) {
				Logging.getLogger().info(
						"QuartzUtil - rescheduleJobs - JobDBCleanup - [ " + triggerForJobDBCleanup.getCronExpression() +" ] ");
				scheduler.rescheduleJob(triggerForJobDBCleanup.getKey(),
						triggerForJobDBCleanup);
			}
			
			// Check if trigger schedule for job update statistics has been changed
			oldtrigger = (CronTrigger) scheduler
					.getTrigger(triggerForJobUpdateStatistics.getKey());
			// If trigger schedule has been changed, reschedule job
			if (!(oldtrigger.getCronExpression().equals(triggerForJobUpdateStatistics
					.getCronExpression()))) {
				Logging.getLogger().info(
						"QuartzUtil - rescheduleJobs - JobUpdateStatistics - [ " + triggerForJobUpdateStatistics.getCronExpression() +" ] ");
				scheduler.rescheduleJob(triggerForJobUpdateStatistics.getKey(),
						triggerForJobUpdateStatistics);
			}
			
			Logging.getLogger().info("QuartzUtil - rescheduleJobs - [ SUCCESSFUL ] ");
			return true;
		} catch (SchedulerException e) {
			Logging.getLogger().error("QuartzUtil - rescheduleJobs - [ FAILED ] ", e);
			return false;
		}
	}

}
